#include "PaintWindow.h"
#include "PaintWindow.h"
#include "angelscript.h"
#include "add_on/scriptstdstring/scriptstdstring.h"
#include "UIRender.h"
#include <iostream>
static void MessageCallbackd(const asSMessageInfo* msg, void* param)
{

}

void PaintWindow::MakeWindow()
{
	__super::MakeWindow();
	InitWindow();
	SDL_SetWindowTitle(window, "temp window");
}

INT PaintWindow::ShowModal()
{
	return __super::ShowModal();
}

void PaintWindow::PrintOnPaintWindow(std::string s)
{
	std::cout << s << std::endl;
}

void PaintWindow::OnMouseUp(tstring name, Control* ctrl, int x, int y)
{
	ctx->Prepare(onmouseup_func);
	int r = ctx->Execute();
	if (r != asEXECUTION_FINISHED)
	{
		// The execution didn't complete as expected. Determine what happened.
		if (r == asEXECUTION_EXCEPTION)
		{
			// An exception occurred, let the script writer know what happened so it can be corrected.
			printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());
		}
	}
}

void PaintWindow::OnMouseDown(tstring name, Control* ctrl, int x, int y)
{
	ctx->Prepare(onmousedown_func);
	int r = ctx->Execute();
	if (r != asEXECUTION_FINISHED)
	{
		// The execution didn't complete as expected. Determine what happened.
		if (r == asEXECUTION_EXCEPTION)
		{
			// An exception occurred, let the script writer know what happened so it can be corrected.
			printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());
		}
	}
}

void PaintWindow::OnKeyUp(tstring name, Control* ctrl, int key)
{

}

void PaintWindow::DoEvent(SDL_Event* evt)
{
	WindowSDL::DoEvent(evt);
	if (evt->type == SDL_MOUSEBUTTONDOWN)
	{
		/*int x = evt->button.x;
		int y = evt->button.y;
		std::pair<tstring, Control*> hit_ctrl = HitTestContrl(vec2(x, y));
		if (hit_ctrl.second != nullptr)
		{
			OnMouseUp(hit_ctrl.first, hit_ctrl.second, x, y);
			hit_ctrl.second->onMouseButtonDown(0, x, y);
		}*/
		this->OnMouseDown("this", nullptr, 0, 0);
	}
	if (evt->type == SDL_MOUSEBUTTONUP)
	{
		/*int x = evt->button.x;
		int y = evt->button.y;

		std::pair<tstring, Control*> hit_ctrl = HitTestContrl(vec2(x, y));
		if (hit_ctrl.second != nullptr)
		{
			OnMouseUp(hit_ctrl.first, hit_ctrl.second, x, y);
			hit_ctrl.second->onMouseButtonUp(0, x, y);
		}*/
		this->OnMouseUp("this", nullptr, 0, 0);
	}
	if (evt->type == SDL_MOUSEMOTION)
	{
		/*int x = evt->button.x;
		int y = evt->button.y;
		for (int i = 0; i < childs.size(); i++)
		{
			childs[i].second->onMouseMove(x, y);
		}*/
	}
	if (evt->type == SDL_KEYUP)
	{
		//cout << evt->key.keysym.scancode << endl;
		int k = evt->key.keysym.sym;
		for (int i = 0; i < childs.size(); i++)
		{
			childs[i].second->onKeyUp(k);
		}
	}

	if (evt->type == SDL_QUIT)
	{
		SDL_Quit();
	}
}

void PaintWindow::OnClosed()
{
	// Clean up
	ctx->Release();
	engine->ShutDownAndRelease();
}

void PaintWindow::OnDraw()
{
	/*	__super::OnDraw();
		UIRender::DrawEdgeRect(0, 0, 200, 200, "#FF00FF");
		UIRender::DrawFillRect(200, 120, 200, 200, "#FF00FF");
		UIRender::DrawFillRect1(200, 200, 150, 234, 15, 144, 41);*/
	/*ctx->Prepare(paint_func);
	if (paint_func) {
		ctx->Execute();
	}*/
	ctx->Prepare(paint_func);
	int r = ctx->Execute();
	if (r != asEXECUTION_FINISHED)
	{
		// The execution didn't complete as expected. Determine what happened.
		if (r == asEXECUTION_EXCEPTION)
		{
			// An exception occurred, let the script writer know what happened so it can be corrected.
			printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());
		}
	}
}

void PaintWindow::OnSizeChange()
{
	ctx->Prepare(onsizechange_func);
	int r = ctx->Execute();
	if (r != asEXECUTION_FINISHED)
	{
		// The execution didn't complete as expected. Determine what happened.
		if (r == asEXECUTION_EXCEPTION)
		{
			// An exception occurred, let the script writer know what happened so it can be corrected.
			printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());
		}
	}
}

void PaintWindow::InitWindow()
{
	__super::OnInitWindow();
	engine = asCreateScriptEngine();

	// Set the message callback to receive information on errors in human readable form.
	int r = engine->SetMessageCallback(asFUNCTION(MessageCallbackd), 0, asCALL_CDECL); assert(r >= 0);

	// AngelScript doesn't have a built-in string type, as there is no definite standard 
	// string type for C++ applications. Every developer is free to register its own string type.
	// The SDK do however provide a standard add-on for registering a string type, so it's not
	// necessary to implement the registration yourself if you don't want to.
	RegisterStdString(engine);
	//UIRender::RegisterUIRender(engine);
	// Register the function that we want the scripts to call 
	//r = engine->RegisterObjectType("Test", sizeof(Test), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<Test>() | asOBJ_APP_CLASS_ALLFLOATS); assert(r >= 0);
	//r = engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL); assert(r >= 0);
	//r = engine->RegisterObjectType("Test", sizeof(Test), asOBJ_VALUE | asOBJ_POD);
	//r = engine->RegisterObjectMethod("Button","void PrintTest()", asMETHOD(Test, PrintTest), asCALL_CDECL);
	//r = engine->RegisterObjectBehaviour("Test", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ComplexDefaultConstructor), asCALL_CDECL_OBJLAST); assert(r >= 0);
	r = engine->RegisterObjectType("PaintWindow", sizeof(*this), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<PaintWindow>() | asOBJ_APP_CLASS_ALLFLOATS); assert(r >= 0);
	r = engine->RegisterObjectMethod("PaintWindow", "void PrintTest(string p)", asMETHODPR(PaintWindow, PrintOnPaintWindow, (string), void), asCALL_THISCALL); assert(r >= 0);
	engine->RegisterGlobalProperty("PaintWindow paintWindow", this);
	r = builder.StartNewModule(engine, "MyModule");
	if (r < 0)
	{
		// If the code fails here it is usually because there
		// is no more memory to allocate the module
		printf("Unrecoverable error while starting a new module.\n");
		return;
	}
	r = builder.AddSectionFromFile("paint.as");
	if (r < 0)
	{
		// The builder wasn't able to load the file. Maybe the file
		// has been removed, or the wrong name was given, or some
		// preprocessing commands are incorrectly written.
		printf("Please correct the errors in the script and try again.\n");
		return;
	}
	r = builder.BuildModule();
	ctx = engine->CreateContext();


	asIScriptModule* mod = engine->GetModule("MyModule");
	init_func = mod->GetFunctionByDecl("void OnInit()");
	if (init_func == 0)
	{
		// The function couldn't be found. Instruct the script writer
		// to include the expected function in the script.
		printf("The script must have the function 'void main()'. Please add it and try again.\n");
		return;
	}
	paint_func = mod->GetFunctionByDecl("void OnPaint()");
	if (paint_func == 0)
	{
		// The function couldn't be found. Instruct the script writer
		// to include the expected function in the script.
		printf("The script must have the function 'void OnPaint()'. Please add it and try again.\n");
		return;
	}
	onmousedown_func = mod->GetFunctionByDecl("void OnMouseDown()");
	if (onmousedown_func == 0)
	{
		// The function couldn't be found. Instruct the script writer
		// to include the expected function in the script.
		printf("The script must have the function 'void OnMouseDown()'. Please add it and try again.\n");
		return;
	}

	onmouseup_func = mod->GetFunctionByDecl("void OnMouseUp()");
	if (onmouseup_func == 0)
	{
		// The function couldn't be found. Instruct the script writer
		// to include the expected function in the script.
		printf("The script must have the function 'void OnMouseUp()'. Please add it and try again.\n");
		return;
	}
	onsizechange_func = mod->GetFunctionByDecl("void OnPaint()");
	if (onsizechange_func == 0)
	{
		// The function couldn't be found. Instruct the script writer
		// to include the expected function in the script.
		printf("The script must have the function 'void OnMouseUp()'. Please add it and try again.\n");
		return;
	}

	// Create our context, prepare it, and then execute

	ctx->Prepare(init_func);
	r = ctx->Execute();
	if (r != asEXECUTION_FINISHED)
	{
		// The execution didn't complete as expected. Determine what happened.
		if (r == asEXECUTION_EXCEPTION)
		{
			// An exception occurred, let the script writer know what happened so it can be corrected.
			printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());
		}
	}
	//// Clean up
	//ctx->Release();
	//engine->ShutDownAndRelease();
}

void PaintWindow::ParseFromXml()
{

}
